package com.mgface.framework;

import com.mgface.framework.entity.RandomEntity;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.actuate.system.ApplicationPidFileWriter;
import org.springframework.boot.actuate.system.EmbeddedServerPortFileWriter;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
//@EnableWebMvc 通常你会为一个Spring MVC应用程序添加@EnableWebMvc,但spring boot看到spring-webmvc在类路径中会自动将其添加,这个注解标志应用程序作为一个web应用程序和激活关键行为例如设置DispatcherServlet等。
//@Configuration 标记此类作为ApplicationContext的beans定义的源
//@EnableAutoConfiguration 告诉Spring Boot启动添加beans基于(classpath设置、其他Beans、各种各样的属性设置)
//@ComponentScan 告诉Spring Boot在根包下面查找components,configurations,和services)注:在根包的情况下这个注解才不需要配置basepackage

//@SpringBootApplication=@EnableWebMvc+@Configuration+@EnableAutoConfiguration+@ComponentScan
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) // 在jvm里面添加--debug展示出应用了哪些自动配置
//@ServletComponentScan扫描Servlet组件时,Servlet、filter、listener可以通过@WebServlet、@WebFilter、@WebListener自动注册
@ServletComponentScan
@EnableConfigurationProperties(value = { RandomEntity.class })
@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled=true)
@Order(1)
public class Application implements CommandLineRunner{
	private final static Logger log = LogManager.getLogger(Application.class);	

	public static void appListener(ApplicationEvent e) {
		LocalDateTime datetime = LocalDateTime.now();
		String currentTime = datetime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
		log.info("触发事件:" + e.getClass().getSimpleName());
		if (e instanceof ApplicationPreparedEvent) {
			log.info("在refresh开始之前,但在bean定义已加载之后触发{ApplicationPreparedEvent}事件,时间为{}",currentTime);
		}
		if (e instanceof ContextRefreshedEvent) {
			log.info("spring上下文被刷新,时间为{}", currentTime);
		}
		if (e instanceof ApplicationReadyEvent) {
			log.info("应用就绪事件,时间为{}", currentTime);
		}
		if (e instanceof EmbeddedServletContainerInitializedEvent) {
			log.info("嵌入式Servlet容器初始化完成,时间为{}", currentTime);
		}
		if (e instanceof ApplicationFailedEvent) {
			log.info("应用启动异常,时间为{},事件为{}", Instant.now().atZone(ZoneId.of("Asia/Shanghai")), "error");
		}
	}

	public static void main(String[] args) throws Exception {
		log.info("main执行开始......");
		/******************第一种*******************/
		// SpringApplication.run(Application.class, args);
		
		/******************第二种:自定义SpringApplication*******************/
		SpringApplication app = new SpringApplication(Application.class);
		// app.setShowBanner(true);
		//创建进程监控的文件
		app.addListeners(Application::appListener,new EmbeddedServerPortFileWriter(),new ApplicationPidFileWriter());
		app.setWebEnvironment(true);// 设置正确类型的ApplicationContext,这里为web项目的applicationContext
		app.setApplicationContextClass(AnnotationConfigEmbeddedWebApplicationContext.class);
		app.setRegisterShutdownHook(true);
		// Map<String, Object> maps = new HashMap<>();
		// maps.put("system.name", "thymeleaf");
		// app.setDefaultProperties(maps);
//		Properties properties = new Properties();
//		try(InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("application_bak.properties")){
//			properties.load(is);
//		};
		//app.setDefaultProperties(properties); // 指定默认的配置文件
		app.setAddCommandLineProperties(false);// 禁用命令行配置
		//application.properoties指定了profile
		//app.setAdditionalProfiles("dev");//添加指定的profile,让使用@Profile("dev")注解生效
//		Set<Object> set = new HashSet<>();
//	    set.add("classpath:applicationContext.xml");  
//	    app.setSources(set);  
		app.run(args);
		
		/******************第三种*******************/
		// new SpringApplicationBuilder().showBanner(true).sources(Parent.class).child(HelloController.class).run(args);
	}

	@Override
	public void run(String... args) throws Exception {
		log.info(">>>>>>>>>>>>>>>服务启动执行,执行加载数据等操作 {} <<<<<<<<<<<<<", Application.class.getSimpleName());
	}

}
